xquery version "1.0";

(:
   The goal of this test is to perform a real-world HTTP request using the
   eXist implementation of the EXPath HTTP Client module.  The sample sends
   a SOAP message to a Web service and displays the result in a human
   readable way.
:)

import module namespace http = "http://expath.org/ns/http-client"
      at "xmldb:exist:///db/expath/http-client.xq";

declare namespace soap = "http://schemas.xmlsoap.org/soap/envelope/";
declare namespace tns  = "http://www.fgeorges.org/ws/test/weather";

(: Unfortunately, the public Web service I used for this example does
   no longer exist.  I use a home-made Web service implementation
   instead, but it is not publicly availble yet.  The principle remain
   the same, though, if you are looking for an example of call of a
   SOAP Web service. :)
declare variable $endpoint as xs:string := "http://localhost:8080/ws-xslt/srv/weather";
declare variable $soap-action as xs:string
      := "http://www.fgeorges.org/ws/test/weather/weather-by-city";

declare function local:send-message()
      as item()+
{
   http:send-request(
      <http:request method="post" href="{ $endpoint }">
         <http:header name="SOAPAction" value="{ $soap-action }"/>
         <http:body content-type="text/xml">
            <soap:Envelope>
               <soap:Header/>
               <soap:Body>
                  <tns:weather-by-city-request>
                     <tns:city>Brussels</tns:city>
                     <tns:country>BE</tns:country>
                  </tns:weather-by-city-request>
               </soap:Body>
            </soap:Envelope>
         </http:body>
      </http:request>
   )
};

declare function local:extract-payload($res as item()+)
      as element(tns:weather-by-city-response)
{
   let $status := xs:integer($res[1]/@status)
   let $weather := $res[2]/soap:Envelope/soap:Body/*
      return
         if ( $status ne 200 ) then
            error(xs:QName('ERRSOAP001'),
                  concat('HTTP error: ', $status, ' - ', $res[1]/@message))
         else if ( empty($weather) ) then
            error(xs:QName('ERRSOAP002'), "SOAP payload is empty?")
         else
            $weather
};

declare function local:format-result($weather as element(tns:weather-by-city-response))
      as xs:string
{
   string-join((
      'Place: ', $weather/tns:place, '&#10;',
      for $d in $weather/tns:detail return $d/concat(
         '  - ', tns:day, ':&#09;', tns:min-temp, ' - ',
         tns:max-temp, ':&#09;', tns:desc, '&#10;'
      )
    ),
   '')
};

let $http-res := local:send-message()
let $payload  := local:extract-payload($http-res)
   return
      local:format-result($payload)
